package org.management.config.handler;

import javassist.NotFoundException;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.UnauthorizedException;
import org.management.base.data.Result;
import org.management.base.data.ResultCode;
import org.management.config.exception.BusinessException;
import org.management.utils.LoggerUtils;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.nio.file.AccessDeniedException;
import java.util.Set;

/**
 * 功能描述
 *
 * @author jy
 * @date 2019/2/26
 * @description
 * @project management
 */
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(BusinessException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Result defaultExceptionHandler(BusinessException e){
        String message = e.getMessage();
        LoggerUtils.error(e.getClass(), message);
        return Result.failure(ResultCode.ERROR.getCode(), ResultCode.ERROR.getDescription());
    }

    /**
     * 非法参数异常
     * @param e IllegalArgumentException 非法参数
     * @return ResultData
     */
    @ExceptionHandler(IllegalArgumentException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Result badRequestException(IllegalArgumentException e) {
        String message = e.getMessage();
        LoggerUtils.error(e.getClass(), message);
        return Result.failure(ResultCode.BAD_REQUEST.getCode(),"非法参数异常");
    }

    /**
     * 请求被拒绝
     * @param e AccessDeniedException
     * @return ResultData
     */
    @ExceptionHandler(AccessDeniedException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Result badMethodExpressException(AccessDeniedException e) {
        String message = e.getMessage();
        LoggerUtils.error(e.getClass(), message);
        return Result.failure(ResultCode.FORBIDDEN.getCode(),"请求被拒绝");
    }

    /**
     * 字段验证异常
     * @param e MethodArgumentNotValidException 字段验证
     * @return ResultData
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Result handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        String message = getExceptionMessage(e.getBindingResult());
        LoggerUtils.error(e.getClass(), message);
        return Result.failure(ResultCode.BAD_REQUEST.getCode(),message);
    }

    @ExceptionHandler(value = BindException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Result handleBeanPropertyBindingResult(BindException e) {
        String message = getExceptionMessage(e.getBindingResult());
        LoggerUtils.error(e.getClass(), message);
        return Result.failure(ResultCode.BAD_REQUEST.getCode(), message);
    }

    /**
     * 约束冲突异常
     * @param e ConstraintViolationException
     * @return ResultData
     */
    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Result handleValidationException(ConstraintViolationException e) {
        StringBuilder sb = new StringBuilder();
        Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
        for (ConstraintViolation constraintViolation : constraintViolations) {
            constraintViolation.getMessage();
            sb.append( constraintViolation.getMessage()).append("|");
        }
        String message = sb.toString();
        LoggerUtils.error(e.getClass(), message);
        return Result.failure(ResultCode.BAD_REQUEST.getCode(), message);
    }

    /**
     * 未授权异常
     */
    @ExceptionHandler(UnauthorizedException.class)
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    public Result handlerUnauthorizedException(UnauthorizedException e) {
        String message = e.getMessage();
        LoggerUtils.error(e.getClass(), message);
        return Result.failure(ResultCode.UNAUTHORIZED.getCode(),"用户未授权");
    }

    /**
     * 没有访问权限
     */
    @ExceptionHandler(AuthorizationException.class)
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    public Result handlerAuthorizationException(AuthorizationException e) {
        String message = e.getMessage();
        LoggerUtils.error(e.getClass(), message);
        return Result.failure(ResultCode.UNAUTHORIZED.getCode(),"用户没有访问权限");
    }


    /**
     * 未找到资源
     */
    @ExceptionHandler(NotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public Result handlerNotFoundException(NotFoundException e) {
        String message = e.getMessage();
        LoggerUtils.error(e.getClass(), message);
        return Result.failure(ResultCode.NOT_FOUND.getCode(),"未找到资源");
    }

    /**
     *
     * @param result 异常信息
     * @return String 异常信息返回
     */
    private String getExceptionMessage(BindingResult result){
        StringBuilder sb = new StringBuilder();
        for (FieldError fieldError : result.getFieldErrors()) {
            sb.append(fieldError.getDefaultMessage()).append("|");
        }
        sb.deleteCharAt(sb.length() - 1);
        return  sb.toString();
    }
}
